<?php

/**
 * 下载
 */
class gd
{

    const dlRootPath = '/home/project/archive/upload/';

    const dbName = 'elva_archive';

    private $dbs = '';

    private $zipname = '';

    protected $config = array(
        'index'
    );

    private $dicList = array(
        'image' => 'attachments_img',
        'audio' => 'attachments_audio',
        'video' => 'attachments_video'
    );

    function init ($method)
    {
        if (! in_array($method, $this->config)) {
            ajaxReturn(400, 'file not exists or not allow');
        }

        $this->dbs = mongoConnections::init()->selectDB(self::dbName);
        $this->$method();
    }

    private function index ()
    {
        $res = array(
            'ret' => 0,
            'msg' => 'request success',
            'data' => []
        );

        set_time_limit(0);
        try {
            $_ids = $this->_validate();

            $result = $this->checkInfos($_ids);

            $this->dispatchLoadMethod($result);
        } catch (\Exception $e) {
            $res['ret'] = $e->getCode();
            $res['msg'] = $e->getMessage();

            ajaxReturn($res['ret'], $res['msg'], $res['data']);
        }
    }

    private function _validate ()
    {
        $ids = isset($_GET['_id']) ? explode(',', $_GET['_id']) : '';

        if (isset($_GET['card_id']) && isset($_GET['type'])) {
            if (! preg_match('/^[0-9a-f]{24}$/', $_GET['card_id']) || ! in_array($_GET['type'], [
                    'image',
                    'audio',
                    'video'
                ])) {
                throw new Exception('param card_id or type validate err', 204);
            }

            $where = [
                '_id' => new MongoId($_GET['card_id'])
            ];
            $fields = [
                'title' => true,
                $this->dicList[$_GET['type']] => true
            ];

            $cardInfo = $this->dbs->selectCollection('archive_card')->findOne($where, $fields);

            if (empty($cardInfo[$this->dicList[$_GET['type']]])) {
                throw new Exception(' card info empty ', 205);
            }

            $this->zipname = $cardInfo['title'];

            $ids = explode(',', $cardInfo[$this->dicList[$_GET['type']]]);
        }

        if (isset($_GET['content_id'])) {
            if (! preg_match('/^[0-9a-f]{24}$/', $_GET['content_id'])) {
                throw new Exception('param content_id validate err', 205);
            }

            $where = [
                '_id' => new MongoId($_GET['content_id'])
            ];
            $fields = [
                'sn' => true,
                'title' => true
            ];

            $contentInfo = $this->dbs->selectCollection('archive_content')->findOne($where, $fields);

            if (empty($contentInfo)) {
                throw new Exception('content info not exists', 206);
            }

            $cardInfo = $this->dbs->selectCollection('archive_card')->find([
                'sn' => $contentInfo['sn']
            ]);
            $cardInfo = iterator_to_array($cardInfo, false);

            if (empty($cardInfo)) {
                throw new Exception('card info not exists', 207);
            }

            $this->zipname = $contentInfo['title'];
            $ids = array();
            foreach ($cardInfo as $k => $v) {
                $ids = array_merge($ids, explode(',', $v['attachments_img']), explode(',', $v['attachments_audio']), explode(',', $v['attachments_video']));
            }
        }

        return array_filter($ids, function ($v)
        {
            return (! preg_match('/^[0-9a-f]{24}$/', $v)) ? false : true;
        });
    }

    private function checkInfos ($ids)
    {
        $fields = array(
            'title' => true,
            'filepath' => true
        );

        if (count($ids) == 1) {
            $where = array(
                '_id' => new MongoId($ids[0])
            );
        } else {
            $where = array(
                '_id' => array(
                    '$in' => array_values(array_map(function (&$v)
                    {
                        return $v = new MongoId($v);
                    }, $ids))
                )
            );
        }

        $collection = $this->dbs->selectCollection('attachment_content');
        $result = iterator_to_array($collection->find($where, $fields), false);

        $attachments = array();
        if (! empty($result)) {
            foreach ($result as $k => $v) {
                $realpath = realpath(self::dlRootPath . $v['filepath']);
                if (file_exists($realpath)) {
                    $attachments[] = array(
                        'title' => $v['title'],
                        'realpath' => $realpath
                    );
                }
            }
        }

        return $attachments;
    }

    private function dispatchLoadMethod ($rs)
    {
        sort($rs);
        if (empty($rs)) {
            echo '没有查找到您要下载的资源';exit;
            throw new \Exception('file info not exist or file not exist', 203);
        }

        if (count($rs) == 1) {
            $this->download($rs[0]);
        } else {
            $this->downloadZip($rs);
        }
    }

    private function download ($rs)
    {
//        ini_set('memory_limit', '5120M');
        ini_set('memory_limit', '-1');

        $realpath = realpath($rs['realpath']);

        if (! file_exists($realpath)) {
            throw new \Exception('file not exist', 202);
        }
        $fcontent = file_get_contents($realpath);
        $filesize = filesize($realpath);

        $dlName = $rs['title'];

        header('Accept-Ranges: bytes');
        header('Accept-Length: ' . $filesize);
        header('Content-Transfer-Encoding: binary');
        header('Content-type: application/octet-stream');
        header('Content-Disposition: attachment; filename=' . $dlName);
        header('Content-Type: application/octet-stream; name=' . $dlName);
        echo $fcontent;
    }

    private function downloadZip ($rs)
    {
        $zipname = $this->zipname ? $this->zipname : substr(basename($rs[0]), 0, strpos(basename($rs[0]), '.'));

        header('X-Accel-Chareset: utf-8');
        header('X-Archive-Files: zip');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename=' . $zipname . '.zip');
        foreach ($rs as $k => $v) {
            /**
             * 文件crc32校验码
             * 文件字节大小十进制
             * 文件访问路径-配合nginx internal 内部subrequest 配置静态资源服务起至 DOWNLOAD_PATH 目录
             * --- static nginx-subrequest 拦截标识
             * 文件在压缩包中解压后的目录层级
             */
            printf("%s %d %s %s\n", '-', filesize($v['realpath']), $v['realpath'], $v['title']);
        }
    }
}
